本文是介绍 HandlerThread
这个类的使用以及源码分析,单从这个类的名称上看,我们就知道这个类可能会和 Handler
和 Thread
有关系。
进入正题以前,我们先来看一下 Handler
、Thread
和 Looper
的关系。
Handler、Thread 和 Looper 的关系
Looper
类别用来为一个线程开启一个消息循环。默认情况下 Android 中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper
对象,开启消息循环)。Looper
对象通过MessageQueue
来存放消息和事件。一个线程只能有一个Looper
,对应一个MessageQueue
。
通常是通过Handler
对象来与Looper
交互的。Handler
可看做是Looper
的一个接口,用来向指定的Looper
发送消息及定义处理方法。- 默认情况下
Handler
会与其被定义时所在线程的Looper
绑定,比如,在主线程中定义,其是与主线程的Looper
绑定。mainHandler = new Handler()
等价于new Handler(Looper.myLooper())
Looper.myLooper()
用来获取当前进程的Looper
对象。
还有一个类似的Looper.getMainLooper()
用于获取主线程的Looper
对象。 在非主线程中直接
new Handler()
会报如下的错误:1
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主线程中默认没有创建
Looper
对象,需要先调用Looper.prepare()
启用Looper
。- 需要先调用
Looper.prepare()
启用Looper
。
调用Looper.loop()
让Looper
开始工作,从消息队列里取消息,处理消息。
注意:写在Looper.loop()
之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()
后,loop 才会中止,其后的代码才能得以运行。
Handler和Thread结合
了解了上面的知识,如果我们想在一个子线程里面处理消息,就需要实现下面的代码:
1 | class LooperThread extends Thread { |
可以看到实现起来比较麻烦。
那么在这种情况下,HandlerThread
应运而生。
HandlerThread 的用法
HandlerThread
是一个包含 Looper
的 Thread
,我们可以直接使用这个 Looper
创建 Handler
。
1 | private HandlerThread mUpdateStatusThread; |
HandlerThread
相当于给 Handler
提供了一个 Looper
,那么多个 Handler
共用一个 HandlerThread
,显然也是可以的。
比如我们需要在后台处理多中任务,可能需要建多个 Handler
(当然在一个 Handler
处理也是可行的),那么我们就可以只创建一个 HandlerThread
,多个 Handler
通过 HandlerThread.getLooper()
来获取 Looper
对象来创建 Handler
。
1 | public class LooperUtils { |
1 | mUpdateStatusHandler = new UpdateStatusHandler(LooperUtils.getThreadLooper(), this); |
源码分析
1 | public class HandlerThread extends Thread { |